package taskadvanced.core.rtm;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.eclipse.jface.preference.IPreferenceStore;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import taskadvanced.Activator;
import taskadvanced.preferences.PreferenceConstants;

public class Service {
	private ParameterContainer parameters;
	private String sharedSecret = "e0c04c19b3d517a8";
	private String api_key = "79f8b46e1eecef0c28247cdfe759fdce";
	private String restURL = "http://api.rememberthemilk.com/services/rest/";
	private String authURL = "http://www.rememberthemilk.com/services/auth/";
	

	public Service(){
		parameters = new ParameterContainer();
	}
	
	public boolean isAuthorized(){
		IPreferenceStore prefs = Activator.getDefault().getPreferenceStore();
		String auth_token = prefs.getString(PreferenceConstants.AUTH_TOKEN);
		
		parameters.clear();
		parameters.add(new Parameter("method","rtm.auth.checkToken"));
		parameters.add(new Parameter("auth_token",auth_token));
		String result = makeQuery("//rsp/@stat");
		System.out.println("result:|"+result+"|");
		return (result.compareToIgnoreCase("ok") == 0);
	}
	
	public URL getAuthURL(){
		String frob = getFrob();
		parameters.clear();
		parameters.add(new Parameter("api_key",api_key));
		parameters.add(new Parameter("perms","delete"));
		parameters.add(new Parameter("frob",frob));
		return prepareQuery(authURL);
	}
	
	public String getFrob() {
		parameters.clear();
		parameters.add(new Parameter("method","rtm.auth.getFrob"));
		
		String frob = makeQuery("//frob");
		IPreferenceStore prefs = Activator.getDefault().getPreferenceStore();
		prefs.setValue(PreferenceConstants.FROB, frob);
		System.out.println("set frob to:"+frob);
		return frob;
	}
	
	public String getToken() {
		IPreferenceStore prefs = Activator.getDefault().getPreferenceStore();
		String frob = prefs.getString(PreferenceConstants.FROB);
		parameters.clear();
		parameters.add(new Parameter("method","rtm.auth.getToken"));
		parameters.add(new Parameter("frob",frob));
		return makeQuery("//token");
	}
	
	public String getTimeline(){
		parameters.clear();
		parameters.add(new Parameter("method","rtm.timelines.create"));
		return makeQuery("//timeline");
	}
	
	public URL prepareQuery(String serviceURL){
		URL url = null;
		try {
			url = new URL(serviceURL + "?" + parameters.getQuery() + "&api_sig=" + getSignature());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		}
		return url;
	}
	
	public String makeQuery(String xpathQuery){
		parameters.add(new Parameter("api_key",api_key));
		
		IPreferenceStore prefs = Activator.getDefault().getPreferenceStore();
		String auth_token = prefs.getString(PreferenceConstants.AUTH_TOKEN);
		parameters.add(new Parameter("auth_token",auth_token));
		
		URL url = prepareQuery(restURL);
		System.out.println(url.toExternalForm());
		InputStream in = null;
		try {
			in = url.openStream();
		} catch (IOException e) {
			e.printStackTrace();
		}
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String aLine,result="";
		try {
			while ( (aLine = br.readLine()) != null ) {
				result += aLine;
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println(result);
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = null;
		try {
			db = factory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			e.printStackTrace();
		}
		InputSource inStream = new InputSource();
		inStream.setCharacterStream(new StringReader(result));
		Document doc1 = null;
		try {
			doc1 = db.parse(inStream);
		} catch (SAXException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		XPathFactory xpathFactory = XPathFactory.newInstance();
		XPath xpath = xpathFactory.newXPath();
		String parsed = null;
		try {
			parsed = xpath.evaluate(xpathQuery, doc1);
		} catch (XPathExpressionException e) {
			e.printStackTrace();
		}
		return parsed;
	}
	
	public void makeQuery(){
		makeQuery("nothing");
	}
	
	public String getSignature() {
		return calculateMD5(sharedSecret + parameters.toString());
	}
	
	public String calculateMD5(String string) {
		try {
			MessageDigest m;
			m = MessageDigest.getInstance("MD5");
			m.update(string.getBytes(),0,string.length());
		    return new BigInteger(1,m.digest()).toString(16);
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
			return null;
		}
	}
	
	public void clearParameters(){
		parameters.clear();
	}
	
	public void addParameter(String key, String value){
		parameters.add(new Parameter(key, value));
	}
	
}
